import Foundation
import CommonCrypto

class BESTIU {
    private let encryptionKey: Data
    private let initializationVector: Data
    
    // 16位纯数字密钥
    private let newAESKey = "A1B2C3D4E5F6G7H8"
    
    // 16位字符偏移量
    private let newAESIV = "I9J0K1L2M3N4O5P6"
    
    init?() {
        guard newAESKey.count == 16, newAESIV.count == 16 else {
            return nil
        }
        
        self.encryptionKey = Data(newAESKey.utf8)
        self.initializationVector = Data(newAESIV.utf8)
    }
    
    func encode(_ input: String) -> String? {
        guard let data = input.data(using: .utf8) else { return nil }
        guard let encryptedData = performCrypt(data: data, operation: CCOperation(kCCEncrypt)) else { return nil }
        return encryptedData.map { String(format: "%02hhx", $0) }.joined()
    }
    
    func decode(_ hexInput: String) -> String? {
        guard let data = convertHexStringToData(hexInput) else { return nil }
        guard let decryptedData = performCrypt(data: data, operation: CCOperation(kCCDecrypt)) else { return nil }
        return String(data: decryptedData, encoding: .utf8)
    }
    
    private func performCrypt(data: Data, operation: CCOperation) -> Data? {
        var outputLength = Int(0)
        var outputBytes = [UInt8](repeating: 0, count: data.count + kCCBlockSizeAES128)
        
        var keyBytes = [UInt8](repeating: 0, count: kCCKeySizeAES128)
        encryptionKey.copyBytes(to: &keyBytes, count: kCCKeySizeAES128)
        
        var ivBytes = [UInt8](repeating: 0, count: kCCBlockSizeAES128)
        initializationVector.copyBytes(to: &ivBytes, count: kCCBlockSizeAES128)
        
        let cryptStatus = CCCrypt(operation,
                                  CCAlgorithm(kCCAlgorithmAES),
                                  CCOptions(kCCOptionPKCS7Padding),
                                  keyBytes,
                                  kCCKeySizeAES128,
                                  ivBytes,
                                  [UInt8](data),
                                  data.count,
                                  &outputBytes,
                                  outputBytes.count,
                                  &outputLength)
        
        if cryptStatus == kCCSuccess {
            return Data(bytes: outputBytes, count: outputLength)
        } else {
            return nil
        }
    }
    
    private func convertHexStringToData(_ hexString: String) -> Data? {
        var data = Data(capacity: hexString.count / 2)
        
        var hex = hexString
        while hex.count > 0 {
            let subIndex = hex.index(hex.startIndex, offsetBy: 2)
            let c = String(hex[..<subIndex])
            hex = String(hex[subIndex...])
            var ch: UInt32 = 0
            Scanner(string: c).scanHexInt32(&ch)
            var byte = UInt8(ch & 0xFF)
            data.append(&byte, count: 1)
        }
        
        return data
    }
}

